#include "Channel.h"
#include <sys/epoll.h>
#include "EventLoop.h"
#include "Logger.h"
namespace mymuduo {

const int Channel::kNoneEvent = 0;
const int Channel::kReadEvent = EPOLLIN | EPOLLPRI;
const int Channel::kWriteEvent = EPOLLOUT;

Channel::Channel(EventLoop *loop, int fd) 
    : loop_(loop)
    , fd_(fd)
    , events_(0)
    , revents_(0)
    , index_(-1)
    , tied_(false) {}

Channel::~Channel(){}

// Channel 的 tie 方法什么时候调用过
void Channel::tie(const std::shared_ptr<void>& obj) {
    tie_ = obj;
    tied_ = true;
}

// 当改变 channel 所表示 fd 的 event 事件后，需要 update 在 poller 更新相应的 fd 事件
// EventLoop => ChannelList，Poller
void Channel::update() {

    // 通过 Channel 所属的 EventLoop，调用 Poller 的相应方法，注册 fd 的 events 事件
    loop_->updateChannel(this);

}

void Channel::remove() {

    // 在 Channel 所属的 EventLoop，把当前的 Channel 删除掉
    loop_->removeChannel(this);

}

void Channel::handleEvent(TimeStamp recieveTime) {
    std::shared_ptr<void> guard;
    if(tied_) {
        guard = tie_.lock();
        if(guard) {
            handleEventWithGuard(recieveTime);
        }
    } else {
        handleEventWithGuard(recieveTime);
    }

}

// 根据 poller 通知的 Channel 发生的具体时间，由 Channel 负责调用相应的回调操作
void Channel::handleEventWithGuard(TimeStamp recieveTime) {
    
    LOG_INFO("func = %s => channel handelEvents revents:%d", __FUNCTION__ ,revents_);
    
    if((revents_ & EPOLLHUP) && !(revents_ & EPOLLIN)) {
        if(closeCallback_) {
            closeCallback_();
        }
    }
    if(revents_ & EPOLLERR) {
        if(errorCallback_) {
            errorCallback_();
        }
    }
    if(revents_ & (EPOLLIN | EPOLLPRI)) {
        if(readCallback_) {
            readCallback_(recieveTime);
        }
    }
    if(revents_ & EPOLLOUT) {
        if(writeCallback_) {
            writeCallback_();
        }
    }
}

}